# --------------------------------------------------------------------------------------------------------------------
# Project:             Digital Payment System (DPS)
# Website:             http://code.google.com/p/dps-x509/
# Purpose of document: This is the main entry point into the creator web site
# --------------------------------------------------------------------------------------------------------------------
from google.appengine.api import users
from google.appengine.ext import db, webapp
from google.appengine.ext.webapp import util
from time import strftime

import urllib
import logging
import base64
import binascii
import sys
import string
import random

#load our vendor packages
sys.path.insert(0, "simplejson")
sys.path.insert(1, "pyasn1")
sys.path.insert(2, "keyczar")
sys.path.insert(3, "dps")

try:
	import simplejson as json
except ImportError:
	import json

try:
	import keyczar.keyinfo as keyinfo
	import keyczar.keys as keys
	import keyczar.util as util
except ImportError:
	from keyczar import *

import dps.asn1CertificateSpecification
import dps.x509Extension

import dps.csr
import dps.csrAsn1Creator
import dps.csrAsn1Extractor
import dps.csrParams
import dps.errors
import dps.utils
import dps.x509Asn1Creator
import dps.x509Asn1Extractor
import dps.x509AttributeAndValue
import dps.x509Certificate
import dps.x509CertificateParams
import dps.x509Helper

class User(db.Model):
    owner_ = db.UserProperty()
    commonName_ = db.StringProperty()
    issuerCert_ = db.TextProperty()
    csr_ = db.TextProperty()
    pk_ = db.TextProperty()

class Type(db.Model):
	owner_ = db.UserProperty()
	tokenType_ = db.StringProperty()
	redeemer_ = db.StringProperty()
	registrar_ = db.StringProperty()

class Certificate(db.Model):
    owner_ = db.UserProperty()
    subject_ = db.StringProperty()
    issuer_ = db.StringProperty()
    redeemer_ = db.StringProperty()
    registrar_ = db.StringProperty()
    tokenType_ = db.StringProperty()
    quantity_ = db.StringProperty()
    cert_ = db.TextProperty()
    privateKey_ = db.TextProperty()
    isMine_ = db.StringProperty()
    signature_ = db.TextProperty()

# --------------------------------------------------------------------------------------------------------------------
def callWebService(name, params, exp):
	""" call the web service and compare expected and actual results
		@param name   - name of the web service to call
		@param params - struct of input parameters
		@param exp    - json str formatted expected results
		@return success, message tuple. success = true if expected result = actual result """
	#print ("executing "+name+" ...");
	res = False
	message = ""
	try:
		global HOST
		#print len(params)
		p = urllib.urlencode(params)
		#print params    
		f = urllib.urlopen(HOST + name, p)
		actual = urllib.unquote(f.read())
		f.close()
		if actual == exp:
			res = True
		else:
			message = "failed. actual len: "+str(len(actual))+" expected:"+str(len(exp))+"\n"
			message += "actual: \n"+actual+"\n expected: \n"+exp
	except:
		message = "Error connecting to web service"
	return res, message

# --------------------------------------------------------------------------------------------------------------------
def standardHeader():
	return "<html><h1>e-token Wallet</h1><hr/>"

# --------------------------------------------------------------------------------------------------------------------
def standardFooter():
	return """<hr/>
			<table>
				<tr><td>&middot</td><td><a href='/creator/'>Home</a></td>
					<td>&middot</td><td><a href='/creator/preToken'>Create Token</a></td>
					<td>&middot</td><td><a href='/creator/preSign'>Transfer Token</a></td>
					<td>&middot</td><td><a href='/creator/type'>Define Token Type</a></td>
					<td>&middot</td><td><a href='/creator/issuerCertDetail'>My Issuer Certificate</a></td>
                    <td>&middot</td><td><a href='/creator/preCsr'>Token Ownership Certificate</a></td>
					<td>&middot</td><td><a href='http://code.google.com/p/dps-x509/wiki/etokenWalletPrototypeDescription'>About</a></td>
					<td>&middot</td><td><a href='https://appengine.google.com/dashboard?app_id=waichet'>Admin</a></td>
					<td>&middot</td><td><a href=%s>Sign Out</a></td><td>&middot</td>
				</tr>
			<table></html>""" % (users.create_logout_url("/"))

# --------------------------------------------------------------------------------------------------------------------
class DpsHandler(webapp.RequestHandler):

	def get(self):
		self.redirect("/creator/")
    
	def post(self):
		self.error(404)

# --------------------------------------------------------------------------------------------------------------------
class MainHandler(DpsHandler):
  
	def get(self):
		user = users.get_current_user()
	
		if user:
			self.redirect("/creator/")
		else:
			self.redirect("/intro/")

# --------------------------------------------------------------------------------------------------------------------
class IntroHandler(DpsHandler):
  
  def get(self):
	user = users.get_current_user()
	
	if user:
		self.redirect("/creator/")
	else:
		self.response.out.write("""<div align=center><h1>Value Transfer Systems <i>Without Third Party Settlement</i></h1>
								<h2>Token Generation and E-Wallet Application</h2>
								<h2><a href=%s>Login</a></h2></div>
								Create tokens, store tokens and transfer tokens to others from this application. You can view documentation <a href="http://code.google.com/p/dps-x509/wiki/etokenWalletPrototypeDescription">about</a> the e-token Wallet prototype.
								<br>To try out the "Token Generation and E-Wallet Application" you are required to <a href=%s>login</a> using your Gmail or Google Account.
								<h2>Concept</h2>The <a href="http://code.google.com/p/dps-x509/">project</a> uses X.509 PKI certificates, as used widely in the internet domain to certify entities. as tokens to represent value as described in the project page."""
								% (users.create_login_url(self.request.uri), users.create_login_url(self.request.uri)))

# --------------------------------------------------------------------------------------------------------------------
class PreIssuerHandler(DpsHandler):

    def get(self):
        user = users.get_current_user()
	
        if not user:
            self.redirect("/intro/")
            return
    
        #Fetch User for current user
        query = db.GqlQuery("SELECT * FROM User WHERE owner_ = :owner "
                            ,owner=users.get_current_user())
        csrs = query.fetch(100)
    
        keys = ""
        for csr in csrs:
            key = dps.utils.stringify(csr.key())
            keys += key
    
        #If first time user then create csr for the user automatically
        if keys == "":
            self.response.out.write("""<h2>Token Issuer Detail</h2>
                                       <TABLE border=0><form method='post' action='/issuer/' enctype='multipart/form-data'>
                                       <tr><th>Common Name: <td><input style='text-transform: lowercase' onkeydown='this.value = this.value.toLowerCase();' required='yes' name='commonName' size=54></textarea><font color='red'>* Common Name field cannot be left empty.</font>
                                       <tr><th>Surname: <td><input required='yes' name='surname' size=54></textarea>
                                       <tr><th>Given Name: <td><input required='yes' name='givenName' size=54></textarea>
                                       <tr><th>Email: <td><input required='yes' name='email' size=54></textarea>
                                       <tr><th>Contact Number: <td><input required='yes' name='contactNumber' size=54></textarea>
                                       <tr><th>URL: <td><input required='yes' name='url' size=54></textarea>
                                       <tr><th>Street: <td><input required='yes' name='street' size=54></textarea>
                                       <tr><th>Locality: <td><input required='yes' name='locality' size=54></textarea>
                                       <tr><th>State: <td><input required='yes' name='state' size=54></textarea>
                                       <tr><th>Postal Code: <td><input required='yes' name='postalCode' size=54></textarea>
                                       <tr><th>Country: <td><input style='text-transform: uppercase' onkeyup='this.value = this.value.toUpperCase();' required='yes' name='country' size=2 maxlength=2></textarea><font size=2>&nbsp;&nbsp;The two-letter ISO code for your country.</font>
                                       <tr><th><td><input type='submit' value='Submit'/>
                                       <input name='format' type='hidden' value='html'/>
                                       </form></table>""")
        else:
            self.redirect("/creator/")
# --------------------------------------------------------------------------------------------------------------------
class IssuerHandler(DpsHandler):

    def post(self):
        user = users.get_current_user()
    
        if not user:
            self.redirect("/intro/")
            return
        
        commonNameStr = ""
        surnameStr = ""
        givenNameStr = ""
        emailStr = ""
        contactNumberStr = ""
        urlStr = ""
        streetStr = ""
        localityStr = ""
        stateStr = ""
        postalCodeStr = ""
        countryStr = ""
        
        try:
            commonNameStr = self.request.get('commonName')
            surnameStr = self.request.get('surname')
            givenNameStr = self.request.get('givenName')
            emailStr = self.request.get('email')
            contactNumberStr = self.request.get('contactNumber')
            urlStr = self.request.get('url')
            streetStr = self.request.get('street')
            localityStr = self.request.get('locality')
            stateStr = self.request.get('state')
            postalCodeStr = self.request.get('postalCode')
            countryStr = self.request.get('country')
        except dps.errors.DPSBaseError, e:
            errorMessage = "Exception: " + str(sys.exc_info()[0])
            dps.utils.out(errorMessage)
            self.response.out.write(errorMessage)
        
        if commonNameStr=="":
            self.redirect("/preIssuer/")
            return
        
        #Fetch User for current user
        query = db.GqlQuery("SELECT * FROM User WHERE owner_ = :owner "
                            ,owner=users.get_current_user())
        csrs = query.fetch(100)
        
        keys = ""
        for csr in csrs:
            key = dps.utils.stringify(csr.key())
            keys += key
        
        #If first time user then create issuer certificate
        if keys == "":
            privateKey = dps.x509Asn1Creator.generatePrivateKey()
            
            #Create issuer certificate(self-signed)
            iParams = dps.x509CertificateParams.X509CertificateParams()
			
            issuer = dps.x509AttributeAndValue.X509AttributeAndValueList()
            iSubject = dps.x509AttributeAndValue.X509AttributeAndValueList()
            if commonNameStr!="":
                commonNameStrItem = dps.x509AttributeAndValue.X509AttributeAndValue(commonNameStr, dps.x509AttributeAndValue.stringRepresentationToOid("commonName"))
                issuer.addItem(commonNameStrItem)
                iSubject.addItem(commonNameStrItem)
            if surnameStr!="":
                surnameStrItem = dps.x509AttributeAndValue.X509AttributeAndValue(surnameStr, dps.x509AttributeAndValue.stringRepresentationToOid("surname"))
                issuer.addItem(surnameStrItem)
                iSubject.addItem(surnameStrItem)
            if givenNameStr!="":
                givenNameStrItem = dps.x509AttributeAndValue.X509AttributeAndValue(givenNameStr, dps.x509AttributeAndValue.stringRepresentationToOid("givenName"))
                issuer.addItem(givenNameStrItem)
                iSubject.addItem(givenNameStrItem)
            if emailStr!="":
                emailStrItem = dps.x509AttributeAndValue.X509AttributeAndValue(emailStr, "1.2.840.113549.1.9.1") #Email OID
                issuer.addItem(emailStrItem)
                iSubject.addItem(emailStrItem)
            if contactNumberStr!="":
                contactNumberStrItem = dps.x509AttributeAndValue.X509AttributeAndValue(contactNumberStr,  dps.x509AttributeAndValue.stringRepresentationToOid("telephoneNumber")) #Email OID
                issuer.addItem(contactNumberStrItem)
                iSubject.addItem(contactNumberStrItem)
            if urlStr!="":
                urlStrItem = dps.x509AttributeAndValue.X509AttributeAndValue(urlStr,  "2.5.29.17") #subjectAltName OID
                issuer.addItem(urlStrItem)
                iSubject.addItem(urlStrItem)
            if streetStr!="":
                streetStrItem = dps.x509AttributeAndValue.X509AttributeAndValue(streetStr, dps.x509AttributeAndValue.stringRepresentationToOid("streetAddress"))
                issuer.addItem(streetStrItem)
                iSubject.addItem(streetStrItem)
            if localityStr!="":
                localityStrItem = dps.x509AttributeAndValue.X509AttributeAndValue(localityStr, dps.x509AttributeAndValue.stringRepresentationToOid("localityName"))
                issuer.addItem(localityStrItem)
                iSubject.addItem(localityStrItem)
            if stateStr!="":
                stateStrItem = dps.x509AttributeAndValue.X509AttributeAndValue(stateStr, dps.x509AttributeAndValue.stringRepresentationToOid("stateOrProvinceName"))
                issuer.addItem(stateStrItem)
                iSubject.addItem(stateStrItem)
            if postalCodeStr!="":
                postalCodeStrItem = dps.x509AttributeAndValue.X509AttributeAndValue(postalCodeStr, dps.x509AttributeAndValue.stringRepresentationToOid("postalCode"))
                issuer.addItem(postalCodeStrItem)
                iSubject.addItem(postalCodeStrItem)
            if countryStr!="":
                countryStrItem = dps.x509AttributeAndValue.X509AttributeAndValue(countryStr, dps.x509AttributeAndValue.stringRepresentationToOid("countryName"))
                issuer.addItem(countryStrItem)
                iSubject.addItem(countryStrItem)
            iParams.setIssuer(issuer)
            iParams.setSubject(iSubject)
            
            i = dps.x509Asn1Creator.X509Asn1Creator(iParams, privateKey)
            i.signWithPrivateKey(privateKey) #or i.signWithPrivateKey(i.getRsaPrivateKey())
            
            issuerCertBase64 = i.getBase64()
            
            #Store user's certificate, CSR and private key in database
            c = User()
            c.owner_ = users.get_current_user()
            c.commonName_ = commonNameStr
            c.issuerCert_ = issuerCertBase64 #or use pretty by changing issuerCertBase64 to issuerCert and removing # infront of issuerCert
            c.csr_ = None #or use pretty by changing csrCertBase64 to csr and removing # infront of csr
            c.pk_ = str(privateKey)
            c.put()
            self.redirect("/creator/")
        else:
            self.redirect("/creator/")

# --------------------------------------------------------------------------------------------------------------------
class CreatorHandler(DpsHandler):

    def get(self):
        user = users.get_current_user()
        
        if not user:
            self.redirect("/intro/")
            return
        
        #Fetch User for current user
        uq = db.GqlQuery("SELECT * FROM User WHERE owner_ = :owner "
                            ,owner=users.get_current_user())
        queries = uq.fetch(100)
        
        keys = ""
        show = ""
        for query in queries:
            key = dps.utils.stringify(query.key())
            keys += key
            if query.csr_ == None:
                show = """<font color='red'>You can't receive any token from other users until you <a href='/creator/preCsr'>create</a> a Token Ownership Certificate</font>"""
            else:
                show = ""
        
        #If first time user then create issuer certificate and csr for the user automatically
        if keys == "":
            self.redirect("/preIssuer/")
        
        notMyToken = ""
        try:
            #Fetch certificate not belonging to the user
            nresults = ""
            nq = db.GqlQuery("SELECT * FROM Certificate WHERE owner_ = :owner AND isMine_ != :isMine"
                             ,owner=users.get_current_user(), isMine=user.nickname())
            ncerts = nq.fetch(100)
            
            for nc in ncerts:
                nkey = dps.utils.stringify(nc.key())
                
                nCertStr = nc.cert_
                nParamRedeemer = ""
                nParamRegistrar = ""
                nParamTokenType = ""
                nParamTokenQuantity = ""
                nCurrentCert = ""
                
                nTempCertStr = urllib.unquote(nCertStr)
                nTempCertChain = dps.x509Helper.certsToBase64(nTempCertStr)
                nCertChain = []
                for nCert in nTempCertChain:
                    nCertChain.append(dps.x509Certificate.X509Certificate.load(nCert))
                
                for ni in range(len(nCertChain)):
                    nCurrentCert = nCertChain[ni]
            
                    nParams = nCurrentCert.getParams()
                    hasTokenData = nParams.hasCompleteTokenData()
            
                    if hasTokenData:
                        nParamRedeemer = nParams.redeemer_
                        nParamRegistrar  = nParams.registrar_
                        nParamTokenType  = nParams.tokenType_    
                        nParamTokenQuantity = nParams.tokenQuantity_
                
                # certBytes = dps.x509Helper.base64ToBytes(nTempCertChain[0])
                # asn1Cert = dps.x509Helper.bytesToAsn1(certBytes, None) # work on here!!
                # asn1Subject = asn1Cert.getComponentByName("subject")
                # asn1Issuer = asn1Cert.getComponentByName("issuer")
                
                nresult = """<tr><td><a href='/creator/certDelete?id=%s'>delete</a></td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td>
                             <td><a href='/creator/certDetail?id=%s'>detail</a></td></tr>""" % \
                             (nkey, nc.subject_, nc.issuer_, nParamRedeemer, nParamRegistrar, nParamTokenType, nParamTokenQuantity, nc.isMine_,nkey)
                nresults += nresult;
                
            if nresults == "":
                notMyToken = ""
            else:
                notMyToken = """<h2>Spent Token</h2><table border='1'>
                                <tr><th></th><th>Subject</th><th>Issuer</th><th>Redeemer</th><th>Registrar</th><th>Token Type</th><th>Quantity</th><th>Transfered to</th></tr>%s</table>""" %nresults
        except:
            self.response.out.write("something wrong for displaying spent token");
            pass
        
        myToken = ""
        try:
            #Fetch certificate belonging to user
            results = ""
            q = db.GqlQuery("SELECT * FROM Certificate WHERE owner_ = :owner AND isMine_ = :isMine"
                            ,owner=users.get_current_user(), isMine=user.nickname())
            certs = q.fetch(100)
            
            for c in certs:
                key = dps.utils.stringify(c.key())
                
                certStr = c.cert_
                paramRedeemer = ""
                paramRegistrar = ""
                paramTokenType = ""
                paramTokenQuantity = ""
                currentCertSig = ""
                prettyPrintText = ""
                currentCert = ""
                
                tempCertStr = urllib.unquote(certStr)
                tempCertChain = dps.x509Helper.certsToBase64(tempCertStr)
                certChain = []
                for cert in tempCertChain:
                    certChain.append(dps.x509Certificate.X509Certificate.load(cert))
                
                for i in range(len(certChain)):
                    currentCert = certChain[i]
            
                    params = currentCert.getParams()
                    hasTokenData = params.hasCompleteTokenData()
            
                    if hasTokenData:
                        paramRedeemer = params.redeemer_
                        paramRegistrar  = params.registrar_
                        paramTokenType  = params.tokenType_    
                        paramTokenQuantity = params.tokenQuantity_
                
                result = """<tr><td><a href='/creator/certDelete?id=%s'>delete</a></td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td>
                            <td><a href='/creator/certDetail?id=%s'>detail</a></td></tr>""" % \
                            (key, c.subject_, c.issuer_, paramRedeemer, paramRegistrar, paramTokenType, paramTokenQuantity, key)
                results += result
            
            if results == "":
                myToken = ""
            else:
                myToken = """<h2>My Token</h2><table border='1'>
                             <tr><th></th><th>Subject</th><th>Issuer</th><th>Redeemer</th><th>Registrar</th><th>Token Type</th><th>Quantity</th></tr>%s</table>""" %results
        except:
            self.response.out.write("something wrong for displaying my token");
            #pass
        
        self.response.out.write(standardHeader()+"""<h2>What do you want to do? """+user.nickname()+"""</h2>%s
								<ul>
									<li><a href='/creator/preToken'>Create Token</a></li>
									<li><a href='/creator/preSign'>Transfer Token</a></li>
									<li><a href='/creator/type'>Define Token Type</a></li>
									<li><a href='/creator/issuerCertDetail'>My Issuer Certificate</a></li>
                                    <li><a href='/creator/preCsr'>Token Ownership Certificate</a></li>
									<li>View documentation <a href='http://code.google.com/p/dps-x509/wiki/etokenWalletPrototypeDescription'>about</a> this e-token Wallet prototype</li>
									<li>Go to the Google App Engine <a href='https://appengine.google.com/dashboard?app_id=waichet'>Admin</a> Console</li>
									<li><a href=%s>Sign Out</a></li>
								</ul>%s%s"""% (show, users.create_logout_url("/"), myToken, notMyToken))

# --------------------------------------------------------------------------------------------------------------------
class CertDeleteHandler(DpsHandler):
  
	def get(self):
		user = users.get_current_user()
		if not user:
			self.redirect("/intro/")
			return
		
		cert = ""
		try:
			certId = self.request.get("id")
			cert = Certificate().get(db.Key(certId))
		except:
			pass
		
		db.delete(cert)
		self.redirect('/creator')

# --------------------------------------------------------------------------------------------------------------------
class CertDetailHandler(DpsHandler):
  
    def get(self):
        user = users.get_current_user()
        if not user:
            self.redirect("/intro/")
            return
        
        certStr = None
        try:
            certId = self.request.get("id")
            cert = Certificate().get(db.Key(certId))
            certStr = cert.cert_
        except:
            pass
        
        paramRedeemer = ""
        paramRegistrar = ""
        paramTokenType = ""
        paramTokenQuantity = ""
        currentCertSig = ""
        prettyPrintText = ""
        
        tempCertStr = urllib.unquote(certStr)
        certChain = dps.x509Helper.certsToBase64(tempCertStr)
        tempCertChain = []
        tokenCertPos = ""
        for c in certChain:
            tempCertChain.append(dps.x509Certificate.X509Certificate.load(c))
        
        for i in range(len(tempCertChain)):
            currentCert = tempCertChain[i]
            
            params = currentCert.getParams()
            hasTokenData = params.hasCompleteTokenData()
            
            if hasTokenData:
                tokenCertPos = i
                paramRedeemer = params.redeemer_
                paramRegistrar  = params.registrar_
                paramTokenType  = params.tokenType_
                paramTokenQuantity = params.tokenQuantity_
        
        certStr = certStr.replace("-----BEGIN CERTIFICATE-----", "-----BEGIN CERTIFICATE-----<br/>")
        certStr = certStr.replace("-----END CERTIFICATE-----", "<br/>-----END CERTIFICATE-----<br/>")
        
        lastCert = dps.x509Asn1Extractor.X509Asn1Extractor(certChain[0])
        certSubject = str(lastCert.getParams().getSubject())
        certIssuer = str(lastCert.getParams().getIssuer())
        posInChain = str(lastCert.getParams().posInChain_)
        certSubject = certSubject.replace(" ", "<br/>")
        certIssuer = certIssuer.replace(" ", "<br/>")
        
        certBytes = dps.x509Helper.base64ToBytes(certChain[tokenCertPos])
        asn1Cert = dps.x509Helper.bytesToAsn1(certBytes, dps.asn1CertificateSpecification.Asn1CertificateSpecification())
        asn1Sig = asn1Cert.getComponentByName("signatureValue")
        
        asn1Sig = str(asn1Sig).replace("(", "")
        asn1Sig = asn1Sig.replace(")", "")
        asn1Sig = asn1Sig.replace(", ", "")
        
        prettyPrintSig = ""
        for i in range(0, len(asn1Sig), 64):
          prettyPrintSig += asn1Sig[i:i+64] + "<br/>"
        
        self.response.out.write(standardHeader()+"""<h2>Token Detail</h2><table border='1'>
                                <tr><th>Subject<td>%s</td></tr><tr><th>Issuer<td>%s</td></tr><tr><th>Redeemer<td>%s</td></tr>
                                <tr><th>Registrar<td>%s</td></tr><tr><th>Token Type<td>%s</td></tr><tr><th>Quantity<td>%s</td></tr>
                                <tr><th>Certificate<td>%s</td><tr><th>Token Signature<td>%s</td></tr><tr><th>Position in Chain<td>%s</td></tr></table>""" % \
                                (certSubject, certIssuer, paramRedeemer, paramRegistrar, paramTokenType, paramTokenQuantity, str(certStr), str(prettyPrintSig), posInChain) +standardFooter())

# --------------------------------------------------------------------------------------------------------------------
class IssuerCertDetailHandler(DpsHandler):

    def get(self):
        user = users.get_current_user()
        if not user:
            self.redirect("/intro/")
            return
        
        query = ""
        myIssuerCert = ""
        q = db.GqlQuery("SELECT * FROM User WHERE owner_ = :owner"
                            ,owner=users.get_current_user())
        queries = q.fetch(100)
        
        for query in queries:
            key = dps.utils.stringify(query.key())
            issuerCertstr = query.issuerCert_
            issuerPrettyPrintText = ""
            
            if issuerCertstr != None:
                for i in range(0, len(issuerCertstr), 64):
                    issuerPrettyPrintText += issuerCertstr[i:i+64] + "<br/>"
                issuerPrettyPrintText = "-----BEGIN CERTIFICATE-----<br/>"+issuerPrettyPrintText+"-----END CERTIFICATE-----"
                
                certChain = dps.x509Helper.certsToBase64(issuerCertstr)
                lastCert = dps.x509Asn1Extractor.X509Asn1Extractor(certChain[0])
                certSubject = str(lastCert.getParams().getSubject())
                certSubject = certSubject.replace(" ", "<br/>")
                
                myIssuerCert = """<tr><th>Subject:<td>%s</td></tr><tr><th>Certificate:<td>%s</td></tr>""" % \
                        (certSubject, issuerPrettyPrintText)
        
        if query == "":
            self.redirect("/preIssuer/")
            return
        
        self.response.out.write(standardHeader()+"""<h2>%s's Issuer Certificate</h2><table border='1'>%s</table>%s""" % \
                               (user.nickname(), myIssuerCert, standardFooter()))

# --------------------------------------------------------------------------------------------------------------------
class preCsrHandler(DpsHandler):

    def get(self):
        user = users.get_current_user()
        if not user:
            self.redirect("/intro/")
            return
        
        csrs = ""
        show = ""
        q = db.GqlQuery("SELECT * FROM User WHERE owner_ = :owner "
                        ,owner=users.get_current_user())
        queries = q.fetch(100)
        
        for query in queries:
            if query.csr_ != None:
                key = dps.utils.stringify(query.key())
                csr = """<tr><td><a href='/creator/deleteCsr?id=%s'>delete</a></td><td>%s</td>
                            <td><a href='/creator/csrDetail?id=%s'>detail</a></td></tr>""" % \
                            (key, query.commonName_, key)
                csrs += csr
        
        if csrs == "":
            show = """<font color='red'>You do not have any Token Owership Certificate</font>"""
        else:
            show = """<h2>Token Ownership Certificate</h2><table border='1'>
                        <tr><th><th>Certificate Common Name</th></tr>%s</table>""" %csrs
            
        self.response.out.write(standardHeader()+"""<h2>Create Token Ownership Certificate(s)</h2>
                                                    <TABLE border=0><form method='post' action='/creator/csr' enctype='multipart/form-data'>
                                                    <tr><th>Common Name: <td><input style='text-transform: lowercase' onkeydown='this.value = this.value.toLowerCase();' required='yes' name='commonName' size=54></textarea><font color='red'>* Common Name field cannot be left empty.</font>
                                                    <tr><th>Surname: <td><input required='yes' name='surname' size=54></textarea>
                                                    <tr><th>Given Name: <td><input required='yes' name='givenName' size=54></textarea>
                                                    <tr><th>Email: <td><input required='yes' name='email' size=54></textarea>
                                                    <tr><th>Contact Number: <td><input required='yes' name='contactNumber' size=54></textarea>
                                                    <tr><th>URL: <td><input required='yes' name='url' size=54></textarea>
                                                    <tr><th>Street: <td><input required='yes' name='street' size=54></textarea>
                                                    <tr><th>Locality: <td><input required='yes' name='locality' size=54></textarea>
                                                    <tr><th>State: <td><input required='yes' name='state' size=54></textarea>
                                                    <tr><th>Postal Code: <td><input required='yes' name='postalCode' size=54></textarea>
                                                    <tr><th>Country: <td><input style='text-transform: uppercase' onkeyup='this.value = this.value.toUpperCase();' required='yes' name='country' size=2 maxlength=2></textarea><font size=2>&nbsp;&nbsp;The two-letter ISO code for your country.</font>
                                                    <tr><th><td><input type='submit' value='Submit'/>
                                                    <input name='format' type='hidden' value='html'/>
                                                    </form></table>%s""" %show +standardFooter())

# --------------------------------------------------------------------------------------------------------------------
class csrHandler(DpsHandler):

    def post(self):
        user = users.get_current_user()
        if not user:
            self.redirect("/intro/")
            return
        
        commonNameStr = ""
        surnameStr = ""
        givenNameStr = ""
        emailStr = ""
        contactNumberStr = ""
        urlStr = ""
        streetStr = ""
        localityStr = ""
        stateStr = ""
        postalCodeStr = ""
        countryStr = ""
        
        try:
            commonNameStr = self.request.get('commonName')
            surnameStr = self.request.get('surname')
            givenNameStr = self.request.get('givenName')
            emailStr = self.request.get('email')
            contactNumberStr = self.request.get('contactNumber')
            urlStr = self.request.get('url')
            streetStr = self.request.get('street')
            localityStr = self.request.get('locality')
            stateStr = self.request.get('state')
            postalCodeStr = self.request.get('postalCode')
            countryStr = self.request.get('country')
        except dps.errors.DPSBaseError, e:
            errorMessage = "Exception: " + str(sys.exc_info()[0])
            dps.utils.out(errorMessage)
            self.response.out.write(errorMessage)
        
        if commonNameStr=="":
            self.redirect("/creator/preCsr")
            return
        
        #Create CSR
        params = dps.csrParams.CsrParams()
        
        subject = dps.x509AttributeAndValue.X509AttributeAndValueList()
        if commonNameStr!="":
            commonNameStrItem = dps.x509AttributeAndValue.X509AttributeAndValue(commonNameStr, dps.x509AttributeAndValue.stringRepresentationToOid("commonName"))
            subject.addItem(commonNameStrItem)
        if surnameStr!="":
            surnameStrItem = dps.x509AttributeAndValue.X509AttributeAndValue(surnameStr, dps.x509AttributeAndValue.stringRepresentationToOid("surname"))
            subject.addItem(surnameStrItem)
        if givenNameStr!="":
            givenNameStrItem = dps.x509AttributeAndValue.X509AttributeAndValue(givenNameStr, dps.x509AttributeAndValue.stringRepresentationToOid("givenName"))
            subject.addItem(givenNameStrItem)
        if emailStr!="":
            emailStrItem = dps.x509AttributeAndValue.X509AttributeAndValue(emailStr, "1.2.840.113549.1.9.1") #Email OID
            subject.addItem(emailStrItem)
        if contactNumberStr!="":
            contactNumberStrItem = dps.x509AttributeAndValue.X509AttributeAndValue(contactNumberStr,  dps.x509AttributeAndValue.stringRepresentationToOid("telephoneNumber")) #Email OID
            subject.addItem(contactNumberStrItem)
        if urlStr!="":
            urlStrItem = dps.x509AttributeAndValue.X509AttributeAndValue(urlStr,  "2.5.29.17") #subjectAltName OID
            subject.addItem(urlStrItem)
        if streetStr!="":
            streetStrItem = dps.x509AttributeAndValue.X509AttributeAndValue(streetStr, dps.x509AttributeAndValue.stringRepresentationToOid("streetAddress"))
            subject.addItem(streetStrItem)
        if localityStr!="":
            localityStrItem = dps.x509AttributeAndValue.X509AttributeAndValue(localityStr, dps.x509AttributeAndValue.stringRepresentationToOid("localityName"))
            subject.addItem(localityStrItem)
        if stateStr!="":
            stateStrItem = dps.x509AttributeAndValue.X509AttributeAndValue(stateStr, dps.x509AttributeAndValue.stringRepresentationToOid("stateOrProvinceName"))
            subject.addItem(stateStrItem)
        if postalCodeStr!="":
            postalCodeStrItem = dps.x509AttributeAndValue.X509AttributeAndValue(postalCodeStr, dps.x509AttributeAndValue.stringRepresentationToOid("postalCode"))
            subject.addItem(postalCodeStrItem)
        if countryStr!="":
            countryStrItem = dps.x509AttributeAndValue.X509AttributeAndValue(countryStr, dps.x509AttributeAndValue.stringRepresentationToOid("countryName"))
            subject.addItem(countryStrItem)
        params.setSubject(subject)
        privateKey = dps.x509Asn1Creator.generatePrivateKey()
        c = dps.csrAsn1Creator.CsrAsn1Creator(params, privateKey)
        
        csrCertBase64 = c.getBase64()
        
        #Store user's certificate, CSR and private key in database
        c = User()
        c.owner_ = users.get_current_user()
        c.commonName_ = commonNameStr
        issuerCert_ = None
        c.csr_ = csrCertBase64 #or use pretty by changing csrCertBase64 to csr and removing # infront of csr
        c.pk_ = str(privateKey)
        c.put()
        self.redirect("/creator/preCsr")

# --------------------------------------------------------------------------------------------------------------------
class deleteCsrHandler(DpsHandler):

    def get(self):
        user = users.get_current_user()
        if not user:
            self.redirect("/intro/")
            return
        
        csr = ""
        try:
            csrId = self.request.get("id")
            csr = User().get(db.Key(csrId))
        except:
            pass
        db.delete(csr)
        self.redirect('/creator/preCsr')

# --------------------------------------------------------------------------------------------------------------------
class csrDetailHandler(DpsHandler):

    def get(self):
        user = users.get_current_user()
        if not user:
            self.redirect("/intro/")
            return
        
        csrStr = ""
        csrPrettyPrintText = ""
        
        try:
            csrId = self.request.get("id")
            csr = User().get(db.Key(csrId))
            csrStr = csr.csr_
            commonNameStr = csr.commonName_
        except:
            pass
        
        csr = dps.csrAsn1Extractor.CsrAsn1Extractor(csrStr)
        csrAsn1Str = str(csr.getParams().getSubject())
        csrAsn1Str = csrAsn1Str.replace(" ", "<br/>")
        
        for i in range(0, len(csrStr), 64):
            csrPrettyPrintText += csrStr[i:i+64] + "<br/>"
        csrPrettyPrintText = "-----BEGIN CERTIFICATE REQUEST-----<br/>"+csrPrettyPrintText+"-----END CERTIFICATE REQUEST-----"
            
        mycsr = """<tr><th>Subject:<td>%s</td></tr><tr><th>Certificate:<td>%s</td></tr>""" % (csrAsn1Str, csrPrettyPrintText)
        
        self.response.out.write(standardHeader()+"""<h2>Token Ownership Certificate - %s</h2><table border='1'>%s</table>%s""" % \
                               (commonNameStr, mycsr, standardFooter()))

# --------------------------------------------------------------------------------------------------------------------
class PreTokenHandler(DpsHandler):
	
    def get(self):
        user = users.get_current_user()
        if not user:
            self.redirect("/intro/")
            return
        
        types = ""
        q = db.GqlQuery("SELECT * FROM Type WHERE owner_ = :owner "
                        ,owner=users.get_current_user())
        results = q.fetch(100)
        for result in results:
            type = """<option value='%s'>%s</option>""" % \
                        (result.tokenType_, result.tokenType_)
            types += type
        
        myToken = ""
        try:
            #Fetch certificate belonging to user
            mtresults = ""
            mtq = db.GqlQuery("SELECT * FROM Certificate WHERE owner_ = :owner AND isMine_ = :isMine"
                                ,owner=users.get_current_user(), isMine=user.nickname())
            mtcerts = mtq.fetch(100)
            
            for c in mtcerts:
                key = dps.utils.stringify(c.key())
                
                certStr = c.cert_
                paramRedeemer = ""
                paramRegistrar = ""
                paramTokenType = ""
                paramTokenQuantity = ""
                currentCertSig = ""
                prettyPrintText = ""
                currentCert = ""
                
                tempCertStr = urllib.unquote(certStr)
                tempCertChain = dps.x509Helper.certsToBase64(tempCertStr)
                certChain = []
                for cert in tempCertChain:
                    certChain.append(dps.x509Certificate.X509Certificate.load(cert))
                
                for i in range(len(certChain)):
                    currentCert = certChain[i]
                    
                    params = currentCert.getParams()
                    hasTokenData = params.hasCompleteTokenData()
                    
                    if hasTokenData:
                        paramRedeemer = params.redeemer_
                        paramRegistrar  = params.registrar_
                        paramTokenType  = params.tokenType_    
                        paramTokenQuantity = params.tokenQuantity_
                
                mtresult = """<tr><td><a href='/creator/certDelete?id=%s'>delete</a></td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td>
                                <td><a href='/creator/certDetail?id=%s'>detail</a></td></tr>""" % \
                                (key, c.subject_, c.issuer_, paramRedeemer, paramRegistrar, paramTokenType, paramTokenQuantity, key)
                mtresults += mtresult
            
            if mtresults == "":
                myToken = ""
            else:
                myToken = """<h2>My Token</h2><table border='1'>
                            <tr><th></th><th>Subject</th><th>Issuer</th><th>Redeemer</th><th>Registrar</th><th>Token Type</th><th>Quantity</th></tr>%s</table>""" %mtresults
        except:
            pass
        
        if types == "":
            self.response.out.write(standardHeader()+"""<h2>Create Token</h2><font color='red'>You haven't defined a token type</font> <br>Please <a href='/creator/type'>define</a> your token type"""+myToken +standardFooter())
        else:
            self.response.out.write(standardHeader()+"""<h2>Create Token</h2>
                                    <TABLE border=0><form method='post' action='/creator/token' enctype='multipart/form-data'>
                                    <tr><th>Token Type: <td><select name=type>%s</select>
                                    <tr><th>Token Quantity: <td><input required='yes' name='quantity' size=15></textarea><font color='red'>*</font>
                                    <input type='hidden' name='isCA' value=true>
                                    <tr><th><td><input type='submit' value='Submit'/>
                                    <input name='format' type='hidden' value='html'/>
                                    </form></table>"""%types +myToken +standardFooter())
 
# --------------------------------------------------------------------------------------------------------------------
class TokenHandler(DpsHandler):
  
    def post(self):
        user = users.get_current_user()
        if not user:
            self.redirect("/intro/")
            return
        
        if self.request.get("quantity") == "":
            self.redirect("/creator/preToken")
            return
        
        subjectStr = ""
        issuerStr = ""
        typeStr = ""
        quantityStr = ""
        isCAStr = ""
        
        redeemerStr = ""
        registrarStr = ""
        q = db.GqlQuery("SELECT * FROM Type WHERE tokenType_ = :type "
                        "AND owner_ = :owner "
                        , type=self.request.get("type"), owner=users.get_current_user())
        results = q.fetch(100)
        for result in results:
            redeemerStr = result.redeemer_
            registrarStr = result.registrar_
        
        id = ""
        q = db.GqlQuery("SELECT * FROM Certificate")
        certs = q.fetch(100)
        for c in certs:
            id = dps.utils.stringify(c.key().id())
        
        if id == "":
            idStr = random.randint(1, 100)
        else:
            idStr = int(id) + random.randint(1, 100)
        
        commonNameStr = ""
        issuerCertStr = ""
        pkStr = ""
        q = db.GqlQuery("SELECT * FROM User WHERE owner_ = :owner "
                        , owner=users.get_current_user())
        csrs = q.fetch(100)
        for csr in csrs:
            if csr.issuerCert_ != None:
                commonNameStr = csr.commonName_
                issuerCertStr = csr.issuerCert_
                pkStr = csr.pk_
        
        pk = keys.RsaPrivateKey.Read(pkStr)
        
        subjectStr = commonNameStr+"-"+str(idStr)
        try:
            issuerStr = commonNameStr
            typeStr = self.request.get("type")
            quantityStr = self.request.get("quantity")
            isCAStr = self.request.get("isCA")
        except dps.errors.DPSBaseError, e:
            errorMessage = "Exception: " + str(sys.exc_info()[0])
            dps.utils.out(errorMessage)
            self.response.out.write(errorMessage)
        
        #Create certificate
        sParams = dps.x509CertificateParams.X509CertificateParams()
        
        sSubject = dps.x509AttributeAndValue.X509AttributeAndValueList()
        sSubjectItem = dps.x509AttributeAndValue.X509AttributeAndValue(subjectStr)
        sSubject.addItem(sSubjectItem)
        sParams.setSubject(sSubject)
        
        certChain = dps.x509Helper.certsToBase64(issuerCertStr)
        issuerCert = dps.x509Asn1Extractor.X509Asn1Extractor(certChain[0])
        sParams.setIssuer(issuerCert.getParams().getIssuer())
		
        sParams.redeemer_ = redeemerStr
        sParams.registrar_ = registrarStr
        sParams.tokenType_ = typeStr
        sParams.tokenQuantity_ = quantityStr
        sParams.isCa_ = True
        
        tokenCert = dps.x509Asn1Creator.X509Asn1Creator(sParams) #X509Asn1Creator creates a new private key
        tokenCert.signWithPrivateKey(pk)
        
        tokenCertExtraStr = "-----BEGIN CERTIFICATE-----%s-----END CERTIFICATE-----" % (tokenCert.getBase64())
        issuerCertExtraStr = "-----BEGIN CERTIFICATE-----%s-----END CERTIFICATE-----" % (issuerCertStr)
        tokenPkStr = str(tokenCert.getRsaPrivateKey())
        cert = "%s%s" % (tokenCertExtraStr, issuerCertExtraStr)
        
        #Store it to database
        c = Certificate()
        c.owner_ = users.get_current_user()
        c.subject_ = subjectStr
        c.issuer_ = issuerStr
        c.redeemer_ = redeemerStr
        c.registrar_ = registrarStr
        c.tokenType_ = typeStr
        c.quantity_ = quantityStr
        c.cert_ = cert
        c.privateKey_ = tokenPkStr
        c.isMine_ = user.nickname()
        c.put()
        
        #Upload certificate created to database
        #params = {"certificate":cert, "format": "json"}
        #result = json.dumps({"returnCode": "Rejected:CertificateAlreadyInRegistrarError"})
        #callWebService("http://dps-x509.appspot.com/registrar/upload", params, result);
        
        #util.WriteFile(cert, "cert.crt")
        #self.response.out.write(standardHeader()+"""<h2>Token Ceritificate</h2>"""+cert+"""<h2>Token Ceritificate Private Key</h2>"""+tokenPkStr +standardFooter())
        self.redirect('/creator/preToken')
    
# --------------------------------------------------------------------------------------------------------------------
class PreSignHandler(DpsHandler):
  
    def get(self):
        user = users.get_current_user()
        if not user:
            self.redirect("/intro/")
            return
        
        tokens = ""
        id = ""
        try:
            #Get token belonging to current user
            q = db.GqlQuery("SELECT * FROM Certificate WHERE owner_ = :owner AND isMine_ = :isMine"
                            ,owner=users.get_current_user(), isMine=user.nickname())
            certs = q.fetch(100)
            for c in certs:
                key = dps.utils.stringify(c.key())
                id = dps.utils.stringify(c.key().id())
                token = """<option value='%s'>%s, %s, %s</option>""" % \
                            (key, c.subject_, c.tokenType_, c.quantity_)
                tokens += token
        except:
            pass
        
        csrs = ""
        cid = ""
        try:
            #Get CSRs of other users
            cq = db.GqlQuery("SELECT * FROM User")
            cresults = cq.fetch(100)
            for cr in cresults:
                if cr.csr_ != None:
                    ckey = dps.utils.stringify(cr.key())
                    cid = dps.utils.stringify(cr.key().id())
                    csr = """<option value='%s'>%s</option>""" % \
                            (ckey, cr.commonName_)
                    csrs += csr
        except:
            pass
        
        notMyToken = ""
        try:
            #Fetch certificate not belonging to the user
            nresults = ""
            nq = db.GqlQuery("SELECT * FROM Certificate WHERE owner_ = :owner AND isMine_ != :isMine"
                            ,owner=users.get_current_user(), isMine=user.nickname())
            ncerts = nq.fetch(100)
            
            for nc in ncerts:
                nkey = dps.utils.stringify(nc.key())
                
                nCertStr = nc.cert_
                nParamRedeemer = ""
                nParamRegistrar = ""
                nParamTokenType = ""
                nParamTokenQuantity = ""
                nCurrentCert = ""
                
                nTempCertStr = urllib.unquote(nCertStr)
                nTempCertChain = dps.x509Helper.certsToBase64(nTempCertStr)
                nCertChain = []
                for nCert in nTempCertChain:
                    nCertChain.append(dps.x509Certificate.X509Certificate.load(nCert))
                
                for ni in range(len(nCertChain)):
                    nCurrentCert = nCertChain[ni]
                    
                    nParams = nCurrentCert.getParams()
                    hasTokenData = nParams.hasCompleteTokenData()
                    
                    if hasTokenData:
                        nParamRedeemer = nParams.redeemer_
                        nParamRegistrar  = nParams.registrar_
                        nParamTokenType  = nParams.tokenType_    
                        nParamTokenQuantity = nParams.tokenQuantity_
                    
                nresult = """<tr><td><a href='/creator/certDelete?id=%s'>delete</a></td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td>
                                <td><a href='/creator/certDetail?id=%s'>detail</a></td></tr>""" % \
                                (nkey, nc.subject_, nc.issuer_, nParamRedeemer, nParamRegistrar, nParamTokenType, nParamTokenQuantity, nc.isMine_,nkey)
                nresults += nresult
                
            if nresults == "":
                notMyToken = ""
            else:
                notMyToken = """<h2>Spent Token</h2><table border='1'>
                                <tr><th></th><th>Subject</th><th>Issuer</th><th>Redeemer</th><th>Registrar</th><th>Token Type</th><th>Quantity</th><th>Transfered to</th></tr>%s</table>""" %nresults
        except:
            pass
        
        if tokens == "":
            self.response.out.write(standardHeader()+"""<h2>Transfer Token</h2><font color='red'>You do not have any tokens to transfer</font><br> Please <a href='/creator/preToken'>go to</a> the token creation page"""+notMyToken +standardFooter())
        elif csrs == "":
            self.response.out.write(standardHeader()+"""<h2>Transfer Token</h2><font color='red'>There are no other users currently available for you to transfer your token to</font>"""+notMyToken +standardFooter())
        else:
            self.response.out.write(standardHeader()+"""<h2>Transfer Token</h2>
                                    <TABLE border=0><form method='post' action='/creator/sign' enctype='multipart/form-data'>
                                    <tr><th>My Token: <td><select name=token>%s</select></td>
                                    <tr><th>Transfer to: <td><select name=csr>%s</select></td>
                                    <tr><th><td><input type='submit' value='Submit'/>
                                    <input name='format' type='hidden' value='html'/>
                                    </form></table>%s%s"""% (tokens, csrs, notMyToken, standardFooter()))

# --------------------------------------------------------------------------------------------------------------------
class SignHandler(DpsHandler):

    def post(self):
        user = users.get_current_user()
        if not user:
            self.redirect("/intro/")
            return
        
        keyStr = ""
        cStr = ""
        
        cert = ""
        ownerStr = ""
        subjectStr = ""
        issuerStr = ""
        redeemerStr = ""
        registrarStr = ""
        tokenTypeStr = ""
        quantityStr = ""
        certStr = ""
        privateKeyStr = ""
        isMineStr = ""
		
        csrOwnerStr = ""
        commonNameStr = ""
        csrStr = ""
        csrPkStr = ""
        
        try:
            keyStr = self.request.get("token")
            cStr = self.request.get("csr")
        except dps.errors.DPSBaseError, e:
            errorMessage = "Exception: " + str(sys.exc_info()[0])
            dps.utils.out(errorMessage)
            self.response.out.write(errorMessage)
        
        try:
            cert = Certificate().get(db.Key(keyStr))
            ownerStr = cert.owner_
            subjectStr = cert.subject_
            issuerStr = cert.issuer_
            redeemerStr = cert.redeemer_
            registrarStr = cert.registrar_
            tokenTypeStr = cert.tokenType_
            quantityStr = cert.quantity_
            certStr = cert.cert_
            privateKeyStr = cert.privateKey_
            isMineStr = cert.isMine_
        except:
            pass
        
        try:
            c = User().get(db.Key(cStr))
            csrOwnerStr = c.owner_
            commonNameStr = c.commonName_
            csrStr = c.csr_
            csrPkStr = c.pk_
        except:
            pass
        
        certChain = dps.x509Helper.certsToBase64(certStr)
        privateKey = keys.RsaPrivateKey.Read(privateKeyStr)
        csr = dps.csrAsn1Extractor.CsrAsn1Extractor(csrStr) #comment dps.csrAsn1Extractor.CsrAsn1Extractor.__init__ print function to hide certificate from displaying (line 54, 59, 65, 66, 67)
        issuerCert = dps.x509Asn1Extractor.X509Asn1Extractor(certChain[0])
        csrPk = keys.RsaPrivateKey.Read(csrPkStr)
        params = dps.x509CertificateParams.X509CertificateParams()
        
        #get certificate count in the certificate chain
        tempCertChain = []
        tokenCertPos = ""
        for c in certChain:
            tempCertChain.append(dps.x509Certificate.X509Certificate.load(c))
        
        for i in range(len(tempCertChain)):
            currentCert = tempCertChain[i]
            
            params = currentCert.getParams()
            hasTokenData = params.hasCompleteTokenData()
            
            if hasTokenData:
                tokenCertPos = i
            
            publicKey = None
            if currentCert.isSelfSigned():
                publicKey = currentCert.getParams().getPublicKey()
            elif publicKey == None:
                publicKey = tempCertChain[i+1].getParams().getPublicKey()
                
            if not publicKey:
                publicKey = currentCert.getIssuerPublicKey()
            if not publicKey:
                raise dps.errors.IssuerPublicKeyNotFoundError("certificate in chain: %d of %d" % (i, len(certChain)))
            
            if not currentCert.verifySignature(publicKey):
                raise dps.errors.InvalidSignatureError()
        
        #Get certifictae signature from certificate containing token details
        certBytes = dps.x509Helper.base64ToBytes(certChain[tokenCertPos])
        asn1Cert = dps.x509Helper.bytesToAsn1(certBytes, dps.asn1CertificateSpecification.Asn1CertificateSpecification())
        asn1Sig = asn1Cert.getComponentByName("signatureValue")
        #remove (), from the signature value
        asn1Sig = str(asn1Sig).replace("(", "")
        asn1Sig = asn1Sig.replace(")", "")
        asn1Sig = asn1Sig.replace(", ", "")
        
        #Create certificate
        params.setIssuer(issuerCert.getParams().getSubject())
        params.setSubject(csr.getParams().getSubject())
        params.id_ = str(asn1Sig)
        params.posInChain_ = tokenCertPos+1
        newCert = dps.x509Asn1Creator.X509Asn1Creator(params, csrPk)
        newCert.signWithPrivateKey(privateKey)
        
        newCertStr = "-----BEGIN CERTIFICATE-----%s-----END CERTIFICATE-----%s" % (newCert.getBase64(), certStr)
        
        try:
            #Put recipient's new certificate details to database
            nCert = Certificate()
            nCert.owner_ = csrOwnerStr
            nCert.subject_ = commonNameStr
            nCert.issuer_ = subjectStr
            nCert.redeemer_ = redeemerStr
            nCert.registrar_ = registrarStr
            nCert.tokenType_ = tokenTypeStr
            nCert.quantity_ = quantityStr
            nCert.cert_ = newCertStr
            nCert.privateKey_ = csrPkStr
            nCert.isMine_ = str(csrOwnerStr)
            nCert.put()
            #Update owner's spent certificate details to database
            sCert = Certificate()
            sCert.owner_ = ownerStr
            sCert.subject_ = subjectStr
            sCert.issuer_ = issuerStr
            sCert.redeemer_ = redeemerStr
            sCert.registrar_ = registrarStr
            sCert.tokenType_ = tokenTypeStr
            sCert.quantity_ = quantityStr
            sCert.cert_ = certStr
            sCert.privateKey_ = privateKeyStr
            sCert.isMine_ = str(csrOwnerStr)
            sCert.put()
            #Delete current owner's certificate on database after updating it to "spent"
            db.delete(cert)
        except:
            pass
        self.redirect('/creator/preSign')
    
# --------------------------------------------------------------------------------------------------------------------
class TypeHandler(DpsHandler):

	def get(self):
		user = users.get_current_user()
		if not user:
			self.redirect("/intro/")
			return
		
		types = ""
		q = db.GqlQuery("SELECT * FROM Type WHERE owner_ = :owner "
						,owner=users.get_current_user())
		set = q.fetch(100)
		
		for s in set:
			key = dps.utils.stringify(s.key())
			type = """<tr><td>%s</td><td>%s</td><td>%s</td>
						<td><a href='/creator/delete?id=%s'>delete</a></td></tr>""" % \
						(s.tokenType_, s.redeemer_, s.registrar_, key)
			types += type
		if types == "":
			show = """<font color='red'>You need to have at least one token type defined before creating a certificate</font>"""
		else:
			show = """<h2>Token Type(s)</h2><table border='1'>
						<tr><th>Token Type</th><th>Redeemer</th><th>Registrar</th></tr>%s</table>""" %types
		
		self.response.out.write(standardHeader()+"""<h2>Define Token Type</h2>
								<TABLE border=0><form method='post' action='/creator/add' enctype='multipart/form-data'>
								<tr><th>Type: <td><input required='yes' name='tokenType' size=54></textarea><font color='red'>*</font>
								<tr><th>Redeemer: <td><input required='yes' name='redeemer' size=54></textarea><font color='red'>*</font>
								<tr><th>Registrar: <td><input required='yes' name='registrar' size=54 value="http://dps-x509.appspot.com/registrar/"></textarea><font color='red'>*</font>
								<tr><th><td><input type='submit' value='Submit'/>
								<input name='format' type='hidden' value='html'/>
								</form></table>%s""" %show +standardFooter())

# --------------------------------------------------------------------------------------------------------------------
class AddHandler(DpsHandler):

	def post(self):
		user = users.get_current_user()
		if not user:
			self.redirect("/intro/")
			return
		
		s = Type()
		s.owner_ = users.get_current_user()
		s.tokenType_ = self.request.get('tokenType')
		s.redeemer_ = self.request.get('redeemer')
		s.registrar_ = self.request.get('registrar')
		s.put()
		self.redirect('/creator/type')

# --------------------------------------------------------------------------------------------------------------------
class DeleteHandler(DpsHandler):

	def get(self):
		user = users.get_current_user()
		if not user:
			self.redirect("/intro/")
			return
		
		type = ""
		try:
			typeId = self.request.get("id")
			type = Type().get(db.Key(typeId))
		except:
			pass
		db.delete(type)
		self.redirect('/creator/type')

# --------------------------------------------------------------------------------------------------------------------
def main():
	dps.utils.setLogMode(dps.utils.LogOutputModes.LOG_ONLY)
	
	application = webapp.WSGIApplication([("/creator/certDelete", CertDeleteHandler),
										("/creator/certDetail", CertDetailHandler),
										("/creator/issuerCertDetail", IssuerCertDetailHandler),
                                        ("/creator/preCsr", preCsrHandler),
                                        ("/creator/csr", csrHandler),
                                        ("/creator/deleteCsr", deleteCsrHandler),
                                        ("/creator/csrDetail", csrDetailHandler),
										("/creator/preToken", PreTokenHandler),
										("/creator/token", TokenHandler),
										("/creator/preSign", PreSignHandler),
										("/creator/sign", SignHandler),
										("/creator/type", TypeHandler),
										("/creator/add", AddHandler),
										("/creator/delete", DeleteHandler),
										("/creator/.*",  CreatorHandler),
                                        ("/preIssuer/.*",  PreIssuerHandler),
                                        ("/issuer/.*",  IssuerHandler),
										("/intro/.*",  IntroHandler),
										("/.*",  MainHandler)],
										debug=True)
	webapp.util.run_wsgi_app(application)

if __name__ == "__main__":
	main()